unit meMainForm;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  XPMenu, ComCtrls, ToolWin, Menus, ExtCtrls, StdCtrls, Buttons, FileCtrl;

type
  TMainForm = class(TForm)
    OpenDialog: TOpenDialog;
    Image1: TImage;
    SaveDialog: TSaveDialog;
    PaintBox: TPaintBox;
    ToolBar: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton7: TToolButton;
    HasTarget: TCheckBox;
    ToolButton8: TToolButton;
    tbNew: TToolButton;
    tbOpen: TToolButton;
    ToolButton12: TToolButton;
    tbSave: TToolButton;
    LB: TListBox;
    sbDown: TSpeedButton;
    BestMove: TEdit;
    Label1: TLabel;
    sbUp: TSpeedButton;
    Button1: TButton;
    Button2: TButton;
    FileListBox1: TFileListBox;
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure FormDestroy(Sender: TObject);
    procedure ToolButton1Click(Sender: TObject);
    procedure tbNewClick(Sender: TObject);
    procedure tbOpenClick(Sender: TObject);
    procedure tbSaveClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure sbUpClick(Sender: TObject);
    procedure sbDownClick(Sender: TObject);
  private
    BlockWidth : Integer;
    BlockHeight: Integer;
    { background=0, player=1, wall=2, floor=3, box=4, target=5, finished=6 }
    Map: array[0..18, 0..15] of Word;

    { User Input }
    MouseDown    : Boolean;
    SelectedTool : Byte;

    MapArea      : TRect;
    WorkingCanvas: TCanvas;

    function GetBlockRect(x, y: Integer): TRect;
    procedure DrawMap(Sender: TObject; var Done: Boolean);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}

function TMainForm.GetBlockRect(x, y: Integer): TRect;
begin
  Result := Rect(MapArea.Left + (BlockWidth  * x),
                 MapArea.Top  + (BlockHeight * y),
                (MapArea.Left + (BlockWidth  * x)) + BlockWidth,
                (MapArea.Top  + (BlockHeight * y)) + BlockHeight);
end;

procedure TMainForm.DrawMap(Sender: TObject; var Done: Boolean);
var
  x, y : Byte;
  Box  : TRect;
begin
  Done := False;

  //Sleep(10);

  for y := Low(Map[0]) to High(Map[0]) do
    for x := Low(Map) to High(Map) do
    begin
      Box := GetBlockRect(x, y);
      StretchBlt(WorkingCanvas.Handle, Box.Left, Box.Top, BlockWidth, BlockHeight,
                 Image1.Canvas.Handle,
                 Map[x, y] * 32, 0,
                 32, 32, SRCCOPY)
    end;

  //Paint the form
  PaintBox.Canvas.CopyRect(MapArea, WorkingCanvas, MapArea);
end;

procedure TMainForm.FormCreate(Sender: TObject);
var
  workDC: HDC;
  Bmp: HBitmap;
begin
  Application.OnIdle := DrawMap;

  BlockWidth  := 32;
  BlockHeight := 32;
  MapArea := Rect(0, 0, Length(Map) * BlockWidth, Length(Map[0]) * BlockHeight);

  WorkingCanvas := TCanvas.Create();
  workDC        := CreateCompatibleDC(Canvas.Handle);
  Bmp := CreateCompatibleBitmap(Canvas.Handle, Screen.Width, Screen.Height);
  SelectObject(workDC, Bmp);
  WorkingCanvas.Handle := workDC;

  SelectedTool := 0;
  MouseDown := False;
  SaveDialog.InitialDir := ExtractFilePath(Application.ExeName);
  OpenDialog.InitialDir := ExtractFilePath(Application.ExeName);
end;

procedure TMainForm.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  x := x div BlockWidth;
  y := y div BlockHeight;
  if (x > high(Map)) or (y > high(Map[0])) then
    Exit;

  Map[x, y] := SelectedTool;

  MouseDown := True;
end;

procedure TMainForm.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if not MouseDown then
    Exit;

  x := x div BlockWidth;
  y := y div BlockHeight;
  if (x > high(Map)) or (y > high(Map[0])) then
    Exit;

  Map[x, y] := SelectedTool;
end;

procedure TMainForm.FormMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  MouseDown := False;
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  WorkingCanvas.Free();
end;

procedure TMainForm.ToolButton1Click(Sender: TObject);
begin
  SelectedTool := TToolButton(Sender).Tag;
end;

procedure TMainForm.tbNewClick(Sender: TObject);
var x, y: byte;
begin
  //clean the map
  for y := Low(Map[0]) to High(Map[0]) do
    for x := Low(Map) to High(Map) do
      Map[x, y] := 0;
end;

procedure TMainForm.tbOpenClick(Sender: TObject);
var
  x, y: Byte;
begin
  if OpenDialog.Execute then
  with TStringList.Create() do
  try
    LoadFromFile(OpenDialog.FileName);

    for y := Low(Map[0]) to High(Map[0]) do
      for x := Low(Map) to High(Map) do
        Map[x, y] := StrToInt(Copy(Strings[y], x + 1, 1));

    { Phan nay thieu muc load HasTarget } 
  finally
    Free();
  end;
end;

procedure TMainForm.tbSaveClick(Sender: TObject);
var
  x, y: Integer;
  s: String;
  TimesFoundBox, TimesFoundTarget, TimesFoundPlayer: Word;
begin

  TimesFoundBox := 0;
  TimesFoundTarget := 0;
  TimesFoundPlayer:=0;
  for y := low(Map[0]) to high(Map[0]) do
    for x := low(Map) to high(Map) do
    begin
      if HasTarget.Checked then Inc(TimesFoundTarget);
      if Map[x, y] = 4 then inc(TimesFoundBox);
      if Map[x, y] = 5 then inc(TimesFoundTarget);
      if Map[x, y] = 1 then inc(TimesFoundPlayer);
    end;


  if TimesFoundPlayer <> 1 then
  begin
    ShowMessage('Recheck player!');
    Exit;
  end;

  if TimesFoundBox <> TimesFoundTarget then
  begin
    ShowMessage('Box <> Target');
    Exit;
  end;

  if SaveDialog.Execute then
  with TStringList.Create() do
  try
    for y := low(Map[0]) to high(Map[0]) do
    begin
      s := '';
      for x := low(Map) to high(Map) do
          s := s + IntToStr(Map[x, y]);
      Add(s);
    end;

    if HasTarget.Checked then Add('1') else Add('0');
    Add(BestMove.Text);


    SaveToFile(savedialog.FileName + '.xbox');
  finally
    Free();
  end;
end;

procedure TMainForm.Button2Click(Sender: TObject);
var x: byte;
    y, z: integer;
    Memo, temp: TStringList;
begin
  if SaveDialog.Execute then
  Memo := TStringList.Create;
  temp := TStringList.Create;


  try
    for x := 0 to (LB.Items.Count - 1) do
    begin
      temp.LoadFromFile(ExtractFilePath(Application.ExeName) + LB.Items.Strings[x]);
      for y:= 0 to (temp.Count-1) do
      Memo.Add(temp.Strings[y]);
    end;

    z:=0;
    repeat
      if memo.Strings[z] = '' then memo.Delete(z)
      else
        inc(z);

    until z=(memo.count-1);

    //reserve 2 header line for additional purposes 
    Memo.Insert(0, '');
    Memo.Insert(0, '');

    memo.SaveToFile(savedialog.FileName);
  finally
    memo.free;
  end;

  temp.free
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
FileListBox1.Update;
LB.Items := FileListBox1.Items;
end;

procedure TMainForm.sbUpClick(Sender: TObject);
var s: string;
begin
if LB.ItemIndex > 0 then
begin
 s:=LB.Items.Strings[LB.ItemIndex - 1];
 LB.Items.Strings[LB.ItemIndex - 1] :=
    LB.Items.Strings[LB.ItemIndex];

 LB.Items.Strings[LB.ItemIndex] := S;

 LB.ItemIndex := LB.ItemIndex - 1;
end

end;

procedure TMainForm.sbDownClick(Sender: TObject);
var s: string;
begin
  if LB.ItemIndex < (LB.Items.Count - 1) then
  begin
   s:=LB.Items.Strings[LB.ItemIndex + 1];
   LB.Items.Strings[LB.ItemIndex + 1] :=
    LB.Items.Strings[LB.ItemIndex];

   LB.Items.Strings[LB.ItemIndex] := S;

   LB.ItemIndex := LB.ItemIndex + 1;
  end;
end;

end.

